/*
 * Digital Audio Mobile - A multi track studio for Windows Mobile
 * Copyright (C) 2008 David Olsson
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <windows.h>
#include <commctrl.h>

#include "SettingsDialog.h"

SettingsDialog::SettingsDialog(HINSTANCE hInstance) throw(): Dialog(hInstance, TEXT("Settings"), CS_OKCANCEL), m_inputDevice(0), m_outputDevice(0), m_latency(0), m_metPlayback(1), m_metRecording(1), m_hasSettings(readSettings()) {
    m_hTabs = CreateWindow(WC_TABCONTROL, 0, WS_CHILD | WS_VISIBLE | TCS_BOTTOM, 0, 0, widthToPixels(width()), heightToPixels(height()), hWnd(), 0, hInstance, 0);
    SendMessage(m_hTabs, CCM_SETVERSION, COMCTL32_VERSION, 0);

    TCITEM item;
    item.mask = TCIF_TEXT;
    item.pszText = TEXT("Audio setup");
    TabCtrl_InsertItem(m_hTabs, 0, &item);
    item.pszText = TEXT("Metronome");
    TabCtrl_InsertItem(m_hTabs, 1, &item);

    RECT rect;
    GetWindowRect(m_hTabs, &rect);
    TabCtrl_AdjustRect(m_hTabs, FALSE, &rect);
    int tabWidth = rect.right - rect.left;
    int tabHeight = rect.bottom - rect.top;
    tabWidth += GetSystemMetrics(SM_CXEDGE) * 2;
    tabHeight += GetSystemMetrics(SM_CYEDGE);

    m_hBackground = CreateWindow(TEXT("STATIC"), 0, WS_CHILD | WS_VISIBLE, 0, 0, tabWidth, tabHeight, m_hTabs, 0, hInstance, 0);

    // Create the controls in the "Audio Setup" tab.
    m_hInputDevLabel = CreateWindow(TEXT("STATIC"), TEXT("Input device:"), WS_CHILD | WS_VISIBLE | SS_LEFT | SS_NOPREFIX, widthToPixels(4), heightToPixels(4), tabWidth - widthToPixels(8), heightToPixels(8), m_hBackground, 0, hInstance, 0);
    m_hInputDev = CreateWindow(TEXT("COMBOBOX"), 0, WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, widthToPixels(4), heightToPixels(16), tabWidth - widthToPixels(8), heightToPixels(64), m_hBackground, 0, hInstance, 0);
    for(unsigned int i = 0; i < m_devFac.numInputDevices(); i++) {
        SendMessage(m_hInputDev, CB_ADDSTRING, 0, LPARAM(m_devFac.inputDeviceName(i)));
    }
    SendMessage(m_hInputDev, CB_SETCURSEL, m_inputDevice, 0);

    m_hOutputDevLabel = CreateWindow(TEXT("STATIC"), TEXT("Output device:"), WS_CHILD | WS_VISIBLE | SS_LEFT | SS_NOPREFIX, widthToPixels(4), heightToPixels(36), tabWidth - widthToPixels(8), heightToPixels(8), m_hBackground, 0, hInstance, 0);
    m_hOutputDev = CreateWindow(TEXT("COMBOBOX"), 0, WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, widthToPixels(4), heightToPixels(48), tabWidth - widthToPixels(8), heightToPixels(64), m_hBackground, 0, hInstance, 0);
    for(unsigned int i = 0; i < m_devFac.numOutputDevices(); i++) {
        SendMessage(m_hOutputDev, CB_ADDSTRING, 0, LPARAM(m_devFac.outputDeviceName(i)));
    }
    SendMessage(m_hOutputDev, CB_SETCURSEL, m_outputDevice, 0);

    m_hLatencyLabel = CreateWindow(TEXT("STATIC"), TEXT("Latency in milliseconds:"), WS_CHILD | WS_VISIBLE | SS_LEFT | SS_NOPREFIX, widthToPixels(4), heightToPixels(68), tabWidth - widthToPixels(8), heightToPixels(8), m_hBackground, 0, hInstance, 0);
    TCHAR buf[128];
    wsprintf(buf, TEXT("%d"), m_latency);
    m_hLatency = CreateWindow(TEXT("EDIT"), buf, WS_BORDER | WS_CHILD | WS_VISIBLE | ES_NUMBER, widthToPixels(4), heightToPixels(80), tabWidth - widthToPixels(8), heightToPixels(12), m_hBackground, 0, hInstance, 0);

    // Create the controls in the "Metronome" tab.
    m_hPlayback = CreateWindow(TEXT("BUTTON"), TEXT("Enable metronome during playback"), WS_CHILD | BS_AUTOCHECKBOX, widthToPixels(4), heightToPixels(4), tabWidth - widthToPixels(8), heightToPixels(12), m_hBackground, 0, hInstance, 0);
    SendMessage(m_hPlayback, BM_SETCHECK, m_metPlayback ? BST_CHECKED : BST_UNCHECKED, 0);
    m_hRecording = CreateWindow(TEXT("BUTTON"), TEXT("Enable metronome during recording"), WS_CHILD | BS_AUTOCHECKBOX, widthToPixels(4), heightToPixels(24), tabWidth - widthToPixels(8), heightToPixels(12), m_hBackground, 0, hInstance, 0);
    SendMessage(m_hRecording, BM_SETCHECK, m_metRecording ? BST_CHECKED : BST_UNCHECKED, 0);
}

SettingsDialog::~SettingsDialog() {
    DestroyWindow(m_hRecording);
    DestroyWindow(m_hPlayback);

    DestroyWindow(m_hLatency);
    DestroyWindow(m_hLatencyLabel);
    DestroyWindow(m_hOutputDev);
    DestroyWindow(m_hOutputDevLabel);
    DestroyWindow(m_hInputDev);
    DestroyWindow(m_hInputDevLabel);

    DestroyWindow(m_hBackground);
    DestroyWindow(m_hTabs);
}

bool SettingsDialog::hasSettings() const throw() {
    return(m_hasSettings);
}

SettingsDialog::Settings SettingsDialog::currentSettings() throw() {
    Settings settings;
    settings.inDev = m_devFac.instantiateInputDevice(SendMessage(m_hInputDev, CB_GETCURSEL, 0, 0));
    settings.outDev = m_devFac.instantiateOutputDevice(SendMessage(m_hOutputDev, CB_GETCURSEL, 0, 0));
    TCHAR buf[128];
    SendMessage(m_hLatency, WM_GETTEXT, 128, LPARAM(buf));
    settings.latency = MusicTime(_tcstol(buf, 0, 10));
    settings.metPlayback = SendMessage(m_hPlayback, BM_GETCHECK, 0, 0) == BST_CHECKED ? true : false;
    settings.metRecording = SendMessage(m_hRecording, BM_GETCHECK, 0, 0) == BST_CHECKED ? true : false;

    return(settings);
}

bool SettingsDialog::readSettings() throw() {
    HKEY hKey;
    if(RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("\\Software\\Digital Audio Mobile"), 0, 0, &hKey) != ERROR_SUCCESS) {
        return(false);
    }

    DWORD type, size = sizeof(DWORD);
    RegQueryValueEx(hKey, TEXT("InputDevice"), 0, &type, LPBYTE(&m_inputDevice), &size);
    RegQueryValueEx(hKey, TEXT("OutputDevice"), 0, &type, LPBYTE(&m_outputDevice), &size);
    RegQueryValueEx(hKey, TEXT("Latency"), 0, &type, LPBYTE(&m_latency), &size);

    RegQueryValueEx(hKey, TEXT("PlaybackMetronome"), 0, &type, LPBYTE(&m_metPlayback), &size);
    RegQueryValueEx(hKey, TEXT("RecordingMetronome"), 0, &type, LPBYTE(&m_metRecording), &size);

    RegCloseKey(hKey);

    return(true);
}

void SettingsDialog::writeSettings() throw() {
    HKEY hKey;
    if(RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("\\Software\\Digital Audio Mobile"), 0, 0, REG_OPTION_NON_VOLATILE, 0, 0, &hKey, 0) == ERROR_SUCCESS) {
        DWORD inputDevice = SendMessage(m_hInputDev, CB_GETCURSEL, 0, 0);
        RegSetValueEx(hKey, TEXT("InputDevice"), 0, REG_DWORD, reinterpret_cast<const BYTE *>(&inputDevice), sizeof(DWORD));

        DWORD outputDevice = SendMessage(m_hOutputDev, CB_GETCURSEL, 0, 0);
        RegSetValueEx(hKey, TEXT("OutputDevice"), 0, REG_DWORD, reinterpret_cast<const BYTE *>(&outputDevice), sizeof(DWORD));

        TCHAR buf[128];
        SendMessage(m_hLatency, WM_GETTEXT, 128, LPARAM(buf));
        DWORD latency = _tcstol(buf, 0, 10);
        RegSetValueEx(hKey, TEXT("Latency"), 0, REG_DWORD, reinterpret_cast<const BYTE *>(&latency), sizeof(DWORD));

        DWORD metPlayback = SendMessage(m_hPlayback, BM_GETCHECK, 0, 0) == BST_CHECKED ? 1 : 0;
        RegSetValueEx(hKey, TEXT("PlaybackMetronome"), 0, REG_DWORD, reinterpret_cast<const BYTE *>(&metPlayback), sizeof(DWORD));

        DWORD metRecording = SendMessage(m_hRecording, BM_GETCHECK, 0, 0) == BST_CHECKED ? 1 : 0;
        RegSetValueEx(hKey, TEXT("RecordingMetronome"), 0, REG_DWORD, reinterpret_cast<const BYTE *>(&metRecording), sizeof(DWORD));
    }
}

void SettingsDialog::showAudioSetup(bool show) throw() {
    int cmd = show ? SW_SHOW : SW_HIDE;
    ShowWindow(m_hInputDevLabel, cmd);
    ShowWindow(m_hInputDev, cmd);
    ShowWindow(m_hOutputDevLabel, cmd);
    ShowWindow(m_hOutputDev, cmd);
    ShowWindow(m_hLatencyLabel, cmd);
    ShowWindow(m_hLatency, cmd);
}

void SettingsDialog::showMetronome(bool show) throw() {
    int cmd = show ? SW_SHOW : SW_HIDE;
    ShowWindow(m_hPlayback, cmd);
    ShowWindow(m_hRecording, cmd);
}

bool SettingsDialog::close(CloseCommand cc) throw() {
    if(cc == CC_OK) {
        writeSettings();
        m_hasSettings = true;
    }

    return(true);
}

void SettingsDialog::controlNotification(HWND hWnd, WPARAM notification) throw() {
    if(hWnd == m_hTabs && notification == TCN_SELCHANGE) {
        switch(TabCtrl_GetCurSel(m_hTabs)) {
            case 0:
                showAudioSetup(true);
                showMetronome(false);
                break;
            case 1:
                showAudioSetup(false);
                showMetronome(true);
                break;
        }
    }
}

void SettingsDialog::menuNotification(unsigned int itemId) throw() {
}
